package com.feng.test.thread;

import java.util.ArrayList;
import java.util.List;

/**
 * @author HuangSuip
 */
public class MultiThread {

    public static void main(String[] args) {

/*        Info info = new Info();
        ProThread proThread = new ProThread(info);
        CumThread cumThread = new CumThread(info);
        new Thread(proThread).start();
        new Thread(cumThread).start();*/

/*        Pool pool = new Pool();
        ProThread2 proThread2 = new ProThread2(pool);
        CumThread2 cumThread2 = new CumThread2(pool);
        new Thread(proThread2).start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(cumThread2).start();*/
        System.out.println("start");
        TestSync sync = new TestSync();
        Long id = 377754479103049728L;
        new Thread(() -> {

            System.out.println(id.hashCode());
            sync.test(id);
        }).start();

        new Thread(() -> {
            //TestSync sync = new TestSync();
            //Long id = 377754479103049728L;
            System.out.println(id.hashCode());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            sync.test(id);
        }).start();
    }
}

class Info {
    private String name = "name";//定义name属性，为了与下面set的name属性区别开
    private String content = "content";// 定义content属性，为了与下面set的content属性区别开
    private boolean flag = true;   // 设置标志位,初始时先生产

    public synchronized void set(String name, String content) {
        while (!flag) {
            try {
                super.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.setName(name);    // 设置名称
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.setContent(content);  // 设置内容
        flag = false; // 改变标志位，表示可以取走
        super.notify();
    }

    public synchronized void get() {
        while (flag) {
            try {
                super.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(this.getName() +
            " --> " + this.getContent());
        flag = true;  // 改变标志位，表示可以生产
        super.notify();
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getContent() {
        return this.content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

class ProThread implements Runnable {
    private Info info = null;      // 保存Info引用

    public ProThread(Info info) {
        this.info = info;
    }

    @Override
    public void run() {
        boolean flag = true;   // 定义标记位
        for (int i = 0; i < 10; i++) {
            if (flag) {
                this.info.set("姓名--" + i, "内容--" + i);    // 设置名称
                flag = false;
            } else {
                this.info.set("姓名--null", "内容--null");    // 设置名称
                flag = true;
            }
        }
    }
}

class CumThread implements Runnable {

    private Info info;

    public CumThread(Info info) {
        this.info = info;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            this.info.get();
        }
    }
}

class Pool {
    private List<String> strings = new ArrayList<>();

    public synchronized void get() {
        while (true) {
            while (!strings.isEmpty()) {
                strings.remove(0);
                System.out.println("消费一个元素");
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("元素消费完毕");
            try {
                System.out.println("消费者调用notify");
                this.notify();
                System.out.println("消费者线程等待");
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public synchronized void set() {
        while (strings.isEmpty()) {
            System.out.println("开始生产");
            for (int i = 0; i < 10; i++) {
                strings.add("第" + i + "个元素");
            }

            try {
                System.out.println("生产完毕,生产者调用notify");
                this.notify();
                System.out.println("生产者线程休息");
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public List<String> getStrings() {
        return strings;
    }
}

class ProThread2 implements Runnable {
    private Pool pool;

    public ProThread2(Pool pool) {
        this.pool = pool;
    }


    @Override
    public void run() {
        pool.set();
    }
}

class CumThread2 implements Runnable {

    private Pool pool;

    public CumThread2(Pool pool) {
        this.pool = pool;
    }

    @Override
    public void run() {
        pool.get();
    }
}

class TestSync {

    public void test(Long id) {
        System.out.println("into");
        synchronized (id) {
            System.out.println("into method");
            try {
                Thread.sleep(3000);
                System.out.println("finish");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
